﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

using SpectationClient.SQLCommandBuilder;
using SpectationClient.DGVExtensions;
using SpectationClient.DataBaseDescription;
using SpectationClient.Async;
using SpectationClient.Stuff;

using Npgsql;


namespace SpectationClient.GUI.UC {
    public partial class ViewImageForm : Form {

        DataGridView DGV = null;
        DataGridViewPhotoColumn imageColumn;
        bool useDB = false;
        bool usePreview = false;


        NpgsqlConnection connection;
 
        Int64 dbImgCount = 0;

        AGetDatabaseObject AGDO;
       
       
        public ViewImageForm() {
            InitializeComponent();
            init(null);
        }

        public ViewImageForm(DataGridViewPhotoColumn imageColumn) {
            InitializeComponent();
            init(imageColumn);
            DataGridView_SelectionChanged(this.DGV, null);
           
        }

        private void init(DataGridViewPhotoColumn imageColumn) {

            this.imageColumn = imageColumn;
            this.DGV = this.imageColumn.DataGridView;
            this.connection = imageColumn.Connection;
            this.Text += String.Format(" \"{0}\"", imageColumn.Name);
            this.DGV.SelectionChanged +=new EventHandler(DataGridView_SelectionChanged);
            this.Icon = Resources.Icon;
            this.Disposed +=new EventHandler(ViewImageForm_Disposed);

            if(imageColumn.PreviewColumn != null) {
                usePreview = true;
                //this.previewColumn = imageColumn.PreviewColumn;
                linkToPreviewColumn();
            }
           
        }

        void ViewImageForm_Disposed(object sender, EventArgs e) {
            if(this.imageColumn != null) {
                DataGridView DGV = this.imageColumn.DataGridView;
                if(DGV != null) DGV.SelectionChanged -= DataGridView_SelectionChanged;
            }
        }


        private void setImage(Image image, String infoText = "" ) {
            if(image != null) this.uC_ImageViewer1.showImage(image);
            //TODO: add info text
        }

        /// <summary>
        /// Connects the Image Viewer with an DGV Image column. Selected images will be shown automatically.
        /// </summary>
        /// <param name="imageColumn"></param>
        /*
        public void linkToImageColumn(DGVExtensions.DataGridViewPhotoColumn imageColumn) {
            this.imageColumn = imageColumn;
            this.imageColumn.DataGridView.SelectionChanged +=new EventHandler(DataGridView_SelectionChanged);
            this.imageColumn.DataGridView.CellValueChanged +=new DataGridViewCellEventHandler(DataGridView_CellValueChanged);
            DataGridView_SelectionChanged(imageColumn.DataGridView, null);
        }*/

        void DataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) {
            if(this.imageColumn != null && e.ColumnIndex == this.imageColumn.Index) {
                DataGridView_SelectionChanged(imageColumn.DataGridView, null);
            }
        }

        /// <summary>
        /// Connects the Image Viewer with an DGV Image column that is supposed to contain small sized preview images.
        /// 
        /// </summary>
        /// <param name="previewColumn"></param>
        
        private void linkToPreviewColumn(){
            useDB = connection != null && !this.imageColumn.IsPreviewColumn;
            FLP_PreviewChoice.Visible = useDB;
            if(useDB) {
                AGDO = new AGetDatabaseObject();
                AGDO.GetDataTableCompleted +=new GetDataTableCompletedEventHandler(AGDO_GetDataTableCompleted);
            }
            
        }

        void AGDO_GetDataTableCompleted(object sender, GetDataTableCompletedEventArgs e) {
            Object key = e.UserState;
            if(e.Cancelled) {
                labelInfoText.Text = "Anfrage abgebrochen";
            } else if(e.Error != null) {
                labelInfoText.Text = e.Error.Message;
            } else {
                if(e.DataTable.Rows.Count > 0 && e.DataTable.Columns[0].DataType == typeof(Byte[])) {
                    Byte[] blob = e.DataTable.Rows[0].ItemArray[0] as Byte[];
                    this.setImage(DataHelper.ByteArrayToImage(blob));
                }
            }
            
        }

        /// <summary>
        /// Reacts on a selection change of the underlying DataGridView an shows new photo.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DataGridView_SelectionChanged(object sender, EventArgs e) {
            
            if(this.DGV == null) return;

            Int32 i = this.imageColumn.Index;

            var selected = from DataGridViewRow row in DGV.Rows
                           where row.Cells[i].Selected
                           select row.Index;
            if(selected.Count() > 0) {
                Int32 iFirst = selected.First();
                DataGridViewRow row = DGV.Rows[selected.First()];
                DataGridViewPhotoCell cell = row.Cells[i] as DataGridViewPhotoCell;
                if(cell == null) return;
           
                Byte[] blob = row.Cells[i].Value as Byte[];
                if(!usePreview) {
                    this.setImage(cell.getImage());
                }else{
                    if(rbUsePreview.Checked){
                        blob = row.Cells[this.imageColumn.PreviewColumn.Index].Value as Byte[];
                        this.setImage(DataHelper.ByteArrayToImage(blob));
                    }

                    if(rbUseOriginal.Checked){
                        
                        blob = row.Cells[this.imageColumn.Index].Value as Byte[];
                        if(blob != null) {
                            this.setImage(DataHelper.ByteArrayToImage(blob));
                        } else {

                            ColumnInfoImageFile ci = this.imageColumn.ColumnInfo;
                            TableInfo ti = ci.Table;

                            ConditionList cl = new ConditionList(ConditionList.Op.AND);

                            foreach(String keyName in ti.PrimaryKey.Names) {
                                cl.Add(new Condition(keyName, Condition.Op.EQ, row.Cells[keyName].Value));
                            }
                            NpgsqlCommand selectScalar = cl.getCmd();

                            selectScalar.CommandText = String.Format("SELECT {0} FROM {1} WHERE {2}",
                                ci.Name, ti.SchemaTableName, selectScalar.CommandText);
                            selectScalar.Connection = this.connection;
                            AGDO.CancelAllRequest();
                            labelInfoText.Text = "Lade Foto aus Datenbank...";
                            timer.Start();
                            AGDO.GetDataTableAsync(selectScalar, ++dbImgCount);
                        }
                        
                    }
                    


                }

            }
            
        }

        void imageColumn_Disposed(object sender, EventArgs e) {
            this.Close();
        }

       

        private void rbUsePreview_CheckedChanged(object sender, EventArgs e) {
            this.DataGridView_SelectionChanged(this.imageColumn.DataGridView, null);
        }

        private Regex endPoints = new Regex(@"\.+$");

        private void timer_Tick(object sender, EventArgs e) {
            if(AGDO.ActiveRequests == 0) {
                timer.Stop();
                labelInfoText.Text = "";
            } else {
                Match m = endPoints.Match(labelInfoText.Text);
                if(!m.Success || m.Value.Length < 3) {
                    labelInfoText.Text+=".";
                } else {
                    labelInfoText.Text = Regex.Replace(labelInfoText.Text, @"\.+$", "", RegexOptions.None);
                }
            }
        }
    }
}
